﻿using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;

namespace Org.LyrcsoftFramework.Cloud.Core
{
    /// <summary>
    /// 代理建造接口
    /// </summary>
    public interface IProxyBuilder
    {
        /// <summary>
        /// 建造代理对象
        /// </summary>
        /// <param name="interfaceType">申明需要实现的接口</param>
        /// <param name="constructor">构造函数参数</param>
        /// <returns></returns>
        Object Build(Type interfaceType, params object[] constructor);

        /// <summary>
        /// 建造代理对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="constructor">构造函数参数</param>
        /// <returns></returns>
        T Build<T>(params object[] constructor);

        public class DefaultProxyBuilder : IProxyBuilder
        {
            public object Build(Type interfaceType, params object[] constructor)
            {
                Type targetType = interfaceType;
                string assemblyName = targetType.Name + "ProxyAssembly";
                string moduleName = targetType.Name + "ProxyModule";
                string typeName = targetType.Name + "Proxy";

                AssemblyName assyName = new AssemblyName(assemblyName);
                AssemblyBuilder assyBuilder = AssemblyBuilder.DefineDynamicAssembly(assyName, AssemblyBuilderAccess.Run);
                ModuleBuilder modBuilder = assyBuilder.DefineDynamicModule(moduleName);

                //新类型的属性
                TypeAttributes newTypeAttribute = TypeAttributes.Class | TypeAttributes.Public;
                //父类型
                Type parentType;
                //要实现的接口
                Type[] interfaceTypes;

                if (targetType.IsInterface)
                {
                    parentType = typeof(Object);
                    interfaceTypes = new Type[] { targetType };
                }
                else
                {
                    parentType = targetType;
                    interfaceTypes = Type.EmptyTypes;
                }
                //得到类型生成器            
                TypeBuilder typeBuilder = modBuilder.DefineType(typeName, newTypeAttribute, parentType, interfaceTypes);
                var resultType = typeBuilder.CreateTypeInfo().AsType();
                var result = Activator.CreateInstance(resultType, args: constructor);
                return result;
            }

            public T Build<T>(params object[] constructor)
            {
                return (T)this.Build(typeof(T), constructor);
            }
        }
    }


}